#include "precompiled.h"
#include "combatrogue.h"
using namespace std;
using namespace weo::engine::item;
using namespace weo::engine::character::rogue;

Combat::Combat()
{
    Meleedps::Init();
    m_Classnr = weo::engine::character::Character::isAllowed("Rogue");
    m_Basevalues.push_back(Attribute("Agility",163));
    m_Basevalues.push_back(Attribute("Intellect",35));
    m_Basevalues.push_back(Attribute("Strength",96));
    m_Basevalues.push_back(Attribute("Stamina",116));
    m_Basevalues.push_back(Attribute("Spirit",59));
    m_Basevalues.push_back(Attribute("CritRating",0.6f*CritRating)); // crit
    m_Basevalues.push_back(Attribute("AttackPower",120)); // ap
    m_Basevalues.push_back(Attribute("Health",3500)); // health
    m_Basevalues.push_back(Attribute("HitRating",5*HitRating)); // hr
    m_Basevalues.push_back(Attribute("CritRating",5*CritRating)); // cr
    m_Basevalues.push_back(Attribute("ExpertiseRating",10*ExpertiseRating)); // expertiserating
    m_Equip.Mode(0);
    BOOST_FOREACH(Attribute attr, m_Basevalues)
    {
        handleAttribute(attr);
    }
    // base settings finished
}
float Combat::evaluateTF()
{
    float wdps1 = m_Equip[46];
    float wdps2 = m_Equip[48];
    float ws1 = m_Equip[47];
    float ws2 = m_Equip[49];
    float baseap = m_Equip[30];
    float crit = m_Equip[6]/CritRating;
    float hit = m_Equip[7]/HitRating;
    float haste = m_Equip[10]/HasteRating;
    // -- glancing blow calculation -- //
    float glancingreduction = 25;
    float glancingprob = 25;
    float glancing = glancingreduction * glancingprob / 100;
    // -- some init values -- //
    bool daggermh = false;
    bool daggeroh = false;
    bool swordspecmh = false;
    bool swordspecoh = false;
    bool critspecmh = false;
    bool critspecoh = false;
    unsigned int mhtype = m_Equip.getItem(14)->Subtype();
    unsigned int ohtype = m_Equip.getItem(15)->Subtype();
    if(mhtype == 5) 
    {
        daggermh = true;
        critspecmh = true;
    }
    else if(mhtype = 1)
    {
        swordspecmh = true;
    }
    else critspecmh = true;
    if(ohtype == 5) 
    {
        daggeroh = true;
        critspecoh = true;
    }
    else if(ohtype = 1)
    {
        swordspecoh = true;
    }
    else critspecoh = true;
    // -- some init values -- //
    float dodge = 6.5f - (m_Equip[51]/ExpertiseRating) * 0.25f;
    float hitwhite = min<float>(100 - 9 - 19 + hit, 100);
    float hityellow = min<float>(100 - 9 + hit, 100);
    float ssenergy = 40;
    float ap = baseap;
    float sndspeed = 0.3f;
    if(m_Equip.hasSpecial(1157515)) // t6 2p
    {
        sndspeed += 0.05f;
    }
    if(m_Equip.hasSpecial(278280)) // warglaives
    {
        haste += 450*0.75/6.0f/HasteRating;
    }
    float calchaste = (1 + sndspeed) * (1 + 0.2f/(120.0f/15.0f)) * (1 + haste / 100); // +snd + haste + bladeflurry
    float ws1hasted = ws1 / calchaste;
    float ws2hasted = ws2 / calchaste;
    float eps = 10 + ((15.0f * 0.2f) / ws2hasted) * (hitwhite-dodge) / 100.0f;// <13 energy per second should be correct, combat potency should be max 3
    // energy per second done
    float fcptime = 5.0f/(eps/ssenergy) - 0.6f*(eps/ssenergy); // time to get 5 cp
    float ssps = 5.0f/fcptime; // ~0.33 combopoints per second = 15s for 5p == sinister strikes per second
    if(m_Equip.hasSpecial(332836)) // ashtongue talisman
    {
        crit += 10.0f/15.0f * 145.0f/CritRating;
    }
    if(m_Equip.hasSpecial(445202))
    {
        crit *=1.03f;
    }
    float critmh = crit + (critspecmh ? 5.0f : 0.0f);
    float critoh = crit + (critspecoh ? 5.0f : 0.0f);
    float critavg = (critmh + critoh) / 2;
    float instantmult = daggermh ? 1.7f : 2.4f; // instant mult for ss
    float instantdmg = wdps1 * ws1;
    float ssmult = 1.1f;
    if(m_Equip.hasSpecial(50727)) // t6 4p
    {
        ssmult *= 1.06f;
    }
    float ssdps = 1 / 100.0f * (hityellow + 1.3f * critmh - dodge) * ssps * ssmult * 1.06f * (instantdmg + ap / 14.0f * instantmult + 98);
    float mhwhitedps = 1 / 100.0f * (hitwhite + critmh - glancing - dodge) * (wdps1 + ap / 14.0f); // normal mh white swing dps
    float ohwhitedps = 0.75f * 1 / 100.0f * (hitwhite + critoh - glancing - dodge) * (wdps2 + ap / 14.0f); // normal oh swing dps
    float extraswings = 1.0f + (0.05f*(swordspecmh ? (hitwhite - dodge) * 1/100.0f : 0.0f)/ws1hasted + 0.05f*(swordspecoh ? (hitwhite - dodge) * 1/100.0f : 0.0f)/ws2hasted);
    float ipoisondps = 1 / 100.0f * 1.12f * (hitwhite - dodge) * 0.83f * ((170 * 0.2f)/ws2hasted); // instant poison dps
    float rdps = 1 / 100.0f * hityellow * (1000 + 0.24f * ap) / (2*fcptime); // rupture dmg per second
    float wfdps = 0;
    if(m_Equip.hasSpecial(707723)) // wftotem
    {
        float wfap = ap + 445 * 1.3f;
        wfdps = 1 / 100.0f * 1 / 100.0f * (hitwhite - dodge) * (hitwhite + critmh - dodge) * 0.2f * (wdps1 + wfap / 14); // wf stuff
    }
    float armorreduction = max<float>((MobArmor - m_Equip[50])/(MobArmor - m_Equip[50] + 10557.5f),0);
    float finaldps = (1.0f-armorreduction) * (calchaste * (extraswings * (mhwhitedps + wfdps) + ohwhitedps)) + ssdps+ rdps + ipoisondps; // sum it up put haste as array mult 
    return m_CondFactor * finaldps;
}
bool filterItemCombat(const weo::engine::item::Item* item)
{
    std::vector<weo::engine::item::Attribute>::const_iterator k;
    const std::vector<Attribute> *attrs = item->Attributes();
    bool badattr = false;
    for(k = attrs->begin();k!=attrs->end();k++)
    {
        switch(k->Type())
        {
        case 20:
        case 21:
            badattr = true;
            break;
        default:
            break;
        }
    }
    return badattr;
}
void Combat::filterEquip(std::vector<std::vector<const weo::engine::item::Item*>>& items)
{
    for(unsigned int i = 0;i<10;i++)
    {
        int subtype = 3;
        if(i == 1 || i == 3)
        {
            items.push_back(m_Database->getPtrbyType(1,i+1));
        }
        else
        {	
            items.push_back(m_Database->getPtrbyType(1,i+1,2));
        }
    }
    items.push_back(m_Database->getPtrbyType(2,0));
    items.push_back(m_Database->getPtrbyType(2,0));
    items.push_back(m_Database->getPtrbyType(3,0));
    items.push_back(m_Database->getPtrbyType(3,0));
    // main hand weapons
    vector<const Item*> mainhand;
    for(int i = 1;i<6;i++)
    {
        if(i == 3) continue;
        for(int j = 1;j<3;j++)
        {
            vector<const Item*> weapon = m_Database->getPtrbyType(4,j,i);
            vector<const Item*>::iterator it;
            for(it=weapon.begin();it!=weapon.end();it++)
            {
                mainhand.push_back(*it);
            }
        }
    }
    // off hand weapons
    vector<const Item*> offhand;
    for(int i = 1;i<6;i++)
    {
        if(i == 3) continue; // no axes
        for(int j = 1;j<4;j+=2)
        {
            vector<const Item*> weapon = m_Database->getPtrbyType(4,j,i);
            vector<const Item*>::iterator it;
            for(it=weapon.begin();it!=weapon.end();it++)
            {
                offhand.push_back(*it);
            }
        }
    }
    items.push_back(mainhand);
    items.push_back(offhand);
    vector<const Item*> ranged;
    for(int i = 9;i<13;i++)
    {
        vector<const Item*> weapon = m_Database->getPtrbyType(4,5,i);
        vector<const Item*>::iterator it;
        for(it=weapon.begin();it!=weapon.end();it++)
        {
            ranged.push_back(*it);
        }
    }
    items.push_back(ranged); // ranged
    items.push_back(m_Database->getPtrbyType(5,0));
    std::vector<std::vector<const weo::engine::item::Item*>>::iterator it;
    for(it = items.begin();it!= items.end();it++)
    {
        it->erase(std::remove_if(it->begin(), it->end(), filterItemCombat),it->end());
    }
    Meleedps::filterEquip(items);
}
void Combat::handleAttribute(const Attribute& attr)
{
    switch(attr.Type())
    {
    default:
        Meleedps::handleAttribute(attr);
        break;
    }
}